import React from 'react'
import './App.css'
import 'antd/dist/antd.css'
import ContextPage from './pages/contextPage/ContextPage'

function App () {

  function f1 (arg) {
    console.log('f1', arg)
    return arg
  }

  function f2 (arg) {
    console.log('f2', arg)
    return arg
  }

  function f3 (arg) {
    console.log('f3', arg)
    return arg
  }

  // 暂时对这个函数还不是很理解，大概可以讲解一下什么情况： 数组的reduce方法，接收两个参数，第一个是一个回调函数，
  // 第二个是一个初始值，具体的可以看MDN，回调函数里可以有四个参数，如果没有初始值的情况下，第一个参数默认为
  // 数组的第一个元素，第二个参数就默认为第二个元素
  function compose (...funcs) {
    return funcs.reduce((a, b) => {
      // 所以这里a,b对应就是第一个和第二个元素
      // console.log(a, b, '555')
      // 注意重点来了，这里返回的应该是对ab进行的操作，比如累加啊，累乘什么的  但是我们这里返回了一个函数，
      // 而且这个函数并不会运行，而是作为reduce方法的下一次的a，或者说累计器，第一个参数，继续传入第二次
      // reduce循环中，也就是第二次循环中，这个函数作为a,然后f3作为b，直到循环结束，
      // 循环结束其实也就是返回了这个函数，如果直接输出返回值可以看到就是这个函数，然后就可以调用该函数，然后就可以达到
      // 合并函数执行的样子了， 注意 这个函数的函数名如果不给它指定的话，他会默认使用我们调用的这个函数名称,
      // 比如我们使用的函数是compose 他就会默认为compose函数， 因为他在循环内部接触不到外面的变量，但是又不能没有名字
      return (...args) => {
        // 注意在循环过程中，其实这个函数一直都没有执行过，一直到结束循环，返回给a然后执行a才开始执行这个函数的
        // 这里其实是闭包的一种运用  因为明明已经结束循环了 但是函数还是可以访问到a , b
        // console.log(...args, a, b, '666')
        return a(b(...args))
      }
    })
  }

  // 这里的a接收到就是这样一个函数     就可以直接调用a    具体可以看上面的分析， 就算参数再多一点也是一样的
  let a = compose(f1, f2, f3, f2, f1, f2, f3)
  console.log(a, 'a')
  // 注意这里的执行 也可以说一下： 返回的这个函数其实是最后一次循环时返回的函数，所以执行这个函数的话，
  // 函数参数中的b就是最后一个参数，a是循环的上一次返回的函数，所以这样依次运行的话，就形成了一种从最后一个开始倒序运行
  // 函数的样式了
  // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#%E5%8A%9F%E8%83%BD%E5%9E%8B%E5%87%BD%E6%95%B0%E7%AE%A1%E9%81%93
  // 这是mdn上面的实现，可以去看看 巧妙的使用了reduce的第二个参数实现 更好理解一些，但是差不多
  let b = a('123')
  console.log(b, 'b')

  return (
    <div className = "App">
      {/* 以下是context（provider与inject）的讲解 */}
      <ContextPage />
    </div>
  )
}

export default App
